package me.evis.mobile.sms2cal.parser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import me.evis.mobile.sms2cal.parser.CompiledCanonicalParseRule.CalEventTemplate;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class CanonicalParseRule {
    public List<String> possibleSenders = new ArrayList<String>();
    public String matchPattern;
    public List<CanonicalParseRule.ParsePattern> parsePatterns = new ArrayList<CanonicalParseRule.ParsePattern>();
    public CompiledCanonicalParseRule.CalEventTemplate calEventTemplate;

    public String toJSON() throws JSONException {
        JSONObject jsonObj = new JSONObject();

        jsonObj.put("possibleSenders", new JSONArray(possibleSenders));
        jsonObj.put("matchPattern", matchPattern);

        JSONArray parsePatternsJson = new JSONArray();
        for (CanonicalParseRule.ParsePattern parsePattern : parsePatterns) {
            JSONObject patternJson = new JSONObject();
            patternJson.put("sequence", parsePattern.sequence);
            patternJson.put("pattern", parsePattern.pattern);
            patternJson.put("matchGroupLabels", new JSONObject(
                    parsePattern.matchGroupLabels));
            parsePatternsJson.put(patternJson);
        }
        jsonObj.put("parsePatterns", parsePatternsJson);

        JSONObject calEventTemplateJson = new JSONObject();
        calEventTemplateJson.put("categoriesTempate", calEventTemplate.categoriesTempate);
        calEventTemplateJson.put("classificationTempate", calEventTemplate.classificationTempate);
        calEventTemplateJson.put("descriptionTempate", calEventTemplate.descriptionTempate);
        calEventTemplateJson.put("dtEndTempate", calEventTemplate.dtEndTempate);
        calEventTemplateJson.put("dtStampTempate", calEventTemplate.dtStampTempate);
        calEventTemplateJson.put("dtStartTempate", calEventTemplate.dtStartTempate);
        calEventTemplateJson.put("locationTempate", calEventTemplate.locationTempate);
        calEventTemplateJson.put("summaryTemplate", calEventTemplate.summaryTemplate);
        jsonObj.put("calEventTemplate", calEventTemplateJson);

        return jsonObj.toString(2);
    }

    public static CanonicalParseRule fromJSON(String json) throws JSONException {
        JSONObject jsonObj = new JSONObject(json);
        CanonicalParseRule rule = new CanonicalParseRule();
        
        JSONArray possibleSendersJson = jsonObj.getJSONArray("possibleSenders");
        for (int i = 0; i < possibleSendersJson.length(); i++) {
            rule.possibleSenders.add(possibleSendersJson.getString(i));
        }
        
        rule.matchPattern = jsonObj.getString("matchPattern");
        
        JSONArray parsePatternsJson = jsonObj.getJSONArray("parsePatterns");
        for (int i = 0; i < parsePatternsJson.length(); i++) {
            JSONObject parsePatternJson = parsePatternsJson.getJSONObject(i);
            int sequence = parsePatternJson.getInt("sequence");
            String pattern = parsePatternJson.getString("pattern");
            ParsePattern parsePattern = new ParsePattern(sequence, pattern);
            
            JSONObject matchGroupLabelsJson = parsePatternJson.getJSONObject("matchGroupLabels");
            for (@SuppressWarnings("unchecked") Iterator<String> iterator = matchGroupLabelsJson.keys(); iterator.hasNext();) {
                String key = iterator.next();
                parsePattern.matchGroupLabels.put(key, matchGroupLabelsJson.getString(key));
            }
            rule.parsePatterns.add(parsePattern);
        }
        
        JSONObject calEventTemplateJson = jsonObj.getJSONObject("calEventTemplate");
        CalEventTemplate calEventTemplate = new CalEventTemplate();
        calEventTemplate.categoriesTempate = calEventTemplateJson.optString("categoriesTempate");
        calEventTemplate.classificationTempate = calEventTemplateJson.optString("classificationTempate");
        calEventTemplate.descriptionTempate = calEventTemplateJson.getString("descriptionTempate");
        calEventTemplate.dtEndTempate = calEventTemplateJson.getString("dtEndTempate");
        calEventTemplate.dtStampTempate = calEventTemplateJson.getString("dtStampTempate");
        calEventTemplate.dtStartTempate = calEventTemplateJson.getString("dtStartTempate");
        calEventTemplate.locationTempate = calEventTemplateJson.getString("locationTempate");
        calEventTemplate.summaryTemplate = calEventTemplateJson.getString("summaryTemplate");
        rule.calEventTemplate = calEventTemplate;
        
        return rule;
    }

    public static class ParsePattern implements Comparable<ParsePattern> {
        public int sequence;
        public String pattern;
        public Map<String, String> matchGroupLabels = new HashMap<String, String>();

        public ParsePattern(int sequence, String pattern) {
            this.sequence = sequence;
            this.pattern = pattern;
        }

        public void addMatchGroupLabel(int index, String label) {
            matchGroupLabels.put(String.valueOf(index), label);
        }

        @Override
        public int compareTo(ParsePattern another) {
            return Integer.valueOf(this.sequence).compareTo(
                    Integer.valueOf(another.sequence));
        }

        @Override
        public String toString() {
            return new StringBuffer().append("sequence:").append(sequence)
                    .append("\n").append("pattern:").append(pattern)
                    .append("\n").append("matchGroupLabels:")
                    .append(matchGroupLabels).append("\n").toString();
        }
    }
}